<?php

    class PhpDb extends PDO // Ainsi un objet de type PhpDb est instanceof PDO
    {
        public $driver = '';
        public $dbh = NULL;

        # constructeur
        public function __construct ( $dsn, $username = NULL, $password = NULL, $driver_options = array() )
        {
            list($this->driver) = explode(':',$dsn);

            if(!in_array($this->driver,self::getAvailableDrivers($this->driver=='pgsql')))
                throw new Exception('Driver indisponible : "'.$this->driver.'"');

            switch($this->driver)
            {
                case 'oci':
                    $class = 'PhpDbDriver'.ucfirst($this->driver);
                    self::load($class);
                    break;
                default:
                    $class = 'PDO';
                    break;
            }
            if(!class_exists($class))
                throw new Exception('Classe indisponible : "'.$class.'"');
            $this->dbh = new $class($dsn,$username,$password,$driver_options);
        }

        # methodes PhpDb
        public static function load($class)
        {
            if($class != 'PhpDbAbstract' && $class != 'PhpDbAbstractStatement')
            {
                self::load('PhpDbAbstract');
                self::load('PhpDbAbstractStatement');
            }
            if(class_exists($class))
                return;
            $file = dirname(__FILE__).'/'.strtolower($class).'.php';
            require_once($file);
            return class_exists($class);
        }

        # methodes PDO
        /*bool*/ public function beginTransaction ( )
        {
            return $this->dbh->beginTransaction();
        }
        /*bool*/ public function commit ( )
        {
            return $this->dbh->commit();
        }
        /*mixed*/ public function errorCode ( )
        {
            return $this->dbh->errorCode();
        }
        /*array*/ public function errorInfo ( )
        {
            return $this->dbh->errorInfo();
        }
        /*int*/ public function exec ( $statement )
        {
            return $this->dbh->exec($statement);
        }
        /*mixed*/ public function getAttribute ( $attribute )
        {
            return $this->dbh->getAttribute($attribute);
        }
        /*array*/ public static function getAvailableDrivers ($is_pg=false)
        {
            $drivers = parent::getAvailableDrivers();
            foreach($drivers as $k=>$driver)
                if(in_array($driver,array('oci')))
                    unset($drivers[$k]);
            if(!$is_pg)
            {
                self::load('PhpDbDriverOci');
                if(PhpDbDriverOci::isAvailable())
                    $drivers[] = 'oci';
            }
            return $drivers;
        }
        /*string*/ public function lastInsertId ( $name = NULL )
        {
            return $this->dbh->lastInsertId($name);
        }
        /*PDOStatement*/ public function prepare ( $statement, $driver_options = array() )
        {
            return $this->dbh->prepare($statement, $driver_options);
        }
        /*PDOStatement*/ public function query ( $statement )
        {
            return $this->dbh->query($statement);
        }
        /*string*/ public function quote ( $string, $parameter_type = self::PARAM_STR )
        {
            return $this->dbh->quote($string, $parameter_type);
        }
        /*bool*/ public function rollBack ( )
        {
            return $this->dbh->rollBack();
        }
        /*bool*/ public function setAttribute ( $attribute, $value )
        {
            return $this->dbh->setAttribute($attribute, $value);
        }
        public function pef($statement,$params=array(),$mode=PDO::FETCH_ASSOC)
        {
            $q = $this->prepare($statement);
            $pos = 1;
            foreach($params as $param)
                if(is_array($param))
                    $q->bindValue($pos++,$param[0],$param[1]);
                else
                    $q->bindValue($pos++,$param,!is_string($param)?PDO::PARAM_INT:PDO::PARAM_STR);
            $r = $q->execute();
            if(!$r && !is_null($r))
                throw new PhpDbQueryException($statement,$params,$this->errorInfo());
            return $q->fetchAll($mode);
        }
        public function pb($statement,$binds=array())
        {
            $q = $this->prepare($statement);
            $pos = 1;
            foreach($binds as $bind)
                $q->bindValue($pos++,$bind[0],$bind[1]);
            $r = $q->execute();
            if(!$r && !is_null($r))
                throw new PhpDbQueryException($statement,$binds,$this->errorInfo());
            return $q;
        }
        public function protect($var)
        {
            return '"'.str_replace(array('.',' '),array('"."','" "'),$var).'"';
        }
        public function getDbh()
        {
            return $this->dbh;
        }
        public function isOracle()
        {
            return in_array($this->driver,array('oci','oracle'));
        }
    }

?>
